﻿/// <reference path="../../js/utils.js" />
'use strict';

define([
    'screenView',
    'commonModels',

    'backgrid.all',

    'backbone.modelbinder',
],
function (
    ScreenView,
    CommonModels,
    Backgrid
) {
    var View = ScreenView.extend({
        super: null,

        name: 'billing',
        title: 'Facturación',

        procedures: {
            bill: {
                delete: App.config.databases.billing + '.BILL.DeleteBill',
                insert: App.config.databases.billing + '.BILL.InsertBill',
                update: App.config.databases.billing + '.BILL.UpdateBill',

                getCurrentBill: App.config.databases.billing + '.BILL.GetCurrentBill',
            },
            billItem: {
                delete: App.config.databases.billing + '.BILL.DeleteBillItem',
                insert: App.config.databases.billing + '.BILL.InsertBillItem',
                update: App.config.databases.billing + '.BILL.UpdateBillItem',
            },
        },
        
        billModel: null,
        billingHistoryColl: null,
        billingItemColl: null,
        billingItemsGrid: null,
        billPrintTemplate: null,
        customersColl: null,
        customersSync: false,
        currentBillLoaded: false,
        fetching: false,
        modelBinder: null,
        productTbx: null,
        productsColl: null,
        productsSync: false,

        events: function() {
            return {
                'click #addProductBtn': '_addProductBtn_click',
                'click #billBtn': '_billBtn_click',
                'click #cleanBtn': '_cleanBtn_click',
                'click #newBtn': '_newBtn_click',
                'click #printBtn': '_printBtn_click',
            };
        },

        constructor: function () {
            this.super = View.__super__;

            this.billModel = new CommonModels.BillModel();

            this.billingItemColl = new CommonModels.BillingItemColl();
            this.billingHistoryColl = new CommonModels.BillingHistoryColl();

            this.customersColl = new CommonModels.CustomerColl();
            this.productsColl = new CommonModels.ProductColl();

            this.modelBinder = new Backbone.ModelBinder();

            return this.super.constructor.apply(this, arguments);
        },

        beforeShow: function (routeArgs) {
            var that = this;

            this.productsColl.fetch({ success: _.bind(this._productsCat_fetch_success, this), });
            this.customersColl.fetch({ success: _.bind(this._customersCat_fetch_success, this), });

            this.getCurrentBill();

            return false;
        },
        addProduct: function (prodCode, prodCount) {
            var result = { success: true, message: '', };
            try {
                var prodMod = this.productsColl.findWhere({ code: prodCode, }),
                    prodCountFixed = parseInt(prodCount, 10);

                if ((result.success == true) && (!prodMod))
                {
                    result.success = false;
                    result.message = 'El producto no es válido.';
                }


                if ((result.success == true) && (prodCount == 0))
                {
                    result.success = false;
                    result.message = 'Ingrese la cantidad de productos.';
                }


                if (result.success == true)
                {
                    var addedProd = this.billingItemColl.findWhere({ code: prodCode });

                    if (addedProd) {
                        result.success = false;
                        result.message = 'El producto ya ha sido ingresado.';
                    }
                }


                if (result.success == true)
                {
                    this.billingItemColl.add(new CommonModels.BillingItemModel({
                        billId: this.billModel.get('id'),
                        name: prodMod.get('name'),
                        code: prodMod.get('code'),
                        pricePerUnit: prodMod.get('price'),
                        productId: prodMod.get('id'),
                        count: prodCountFixed,
                    }));
                }
            }
            catch (Error) {
                console.error(Error);

                result.success = false;
                result.message = 'Error al agregar un product.';
            }

            return result;
        },
        cleanBilling: function (options) {
            if (!options) options = {};

            App.mainService.runProcedure(
                {
                    Procedure: this.procedures.bill.delete,
                    Parameters: [
                        { Name: 'id', Value: this.billModel.get('id'), },
                    ],
                },
                {
                    success: function (resp) {
                        if (resp.Success == true) {
                            if (options.success) options.success(resp);
                        }
                    },
                    error: function () {
                        console.debug("error");
                    },
                }
            );

            return this;
        },
        delegateModelEvents: function () {
            this.listenTo(this.billModel, 'change', this._billModel_change, this)
                .listenTo(this.billModel, 'change reset', this._billModel_changeReset, this)
                .listenTo(this.billingItemColl, 'add', this._billingItemColl_add, this)
                .listenTo(this.billingItemColl, 'change', this._billingItemColl_change, this)
                .listenTo(this.billingItemColl, 'remove', this._billingItemColl_remove, this)
                .listenTo(this.billingItemColl, 'add change remove reset', this._billingItemColl_addChangeRemoveReset, this)
                //.listenTo(this.customersColl, 'sync', this._customerColl_sync, this)
                .listenTo(this.model, 'change:customer', this._model_change_customer, this)
                .listenTo(this.model, 'change:pay', this._model_change_pay, this);

            return this.super.delegateModelEvents.apply(this, arguments);
        },
        fetchBill: function (id) {
            var that = this;

            this.fetching = true;

            this.billModel.fetch(
                [{ Name: 'id', Value: id, }],
                {
                    success: function (model, resp) {
                        try
                        {
                            that.billingItemColl.setRaw(resp.Data[1]);

                            that.fetching = false;

                            that.syncModels();
                        }
                        catch (Error) { console.error(Error); }
                    },
                    error: function () {
                        console.debug("error");
                    },
                }
            );
        },
        getBillForPrint: function (billModel, billingItemColl) {
            var billPrint,
                customerModel = this.customersColl.findWhere({ id: billModel.get('customerId'), }),
                priceFormatter = new Backgrid.NumberFormatter(),
                that = this,
                totalPrice = 0;

            billPrint = {
                id: utils.misc.padLeft(billModel.get('id'), '00000000'),
                customerAddress: (customerModel) ? customerModel.get('address') : '',
                customerCity: (customerModel) ? customerModel.get('city') : '',
                customerCode: (customerModel) ? customerModel.get('code') : '',
                customerName: (customerModel) ? customerModel.get('name') : '',
                customerTelephone: (customerModel) ? customerModel.get('telephone') : '',
                items: [],
                price: 0,
            };

            billingItemColl.each(function (billItemModel) {
                var productModel = that.productsColl.findWhere({ id: billItemModel.get('productId'), }),
                    price,
                    count;

                price = billItemModel.get('pricePerUnit');
                count = billItemModel.get('count');

                billPrint.items.push({
                    code: (productModel) ? productModel.get('code') : '',
                    count: count,
                    description: (productModel) ? productModel.get('description') : '',
                    subTotal: priceFormatter.fromRaw(price * count),
                    price: priceFormatter.fromRaw(price),
                });


                totalPrice += price * count;
            });


            billPrint.price = priceFormatter.fromRaw(totalPrice);


            return billPrint;
        },
        getCurrentBill: function () {
            var that = this;

            this.fetching = true;

            App.mainService.runProcedure(
                {
                    Procedure: this.procedures.bill.getCurrentBill,
                },
                {
                    success: function (resp) {
                        if (resp.Success == true) {
                            var data = resp.Data[0][0];

                            if (data) {
                                that.billModel.set({
                                    id: data.Id,
                                    customerId: data.CustomerId,
                                    datetime: data.Datetime,
                                    pay: data.Pay,
                                    sealed: data.Sealed,
                                });

                                that.billingItemColl.setRaw(resp.Data[1]);
                            }

                            that.fetching = false;

                            that.currentBillLoaded = true;

                            that.triggerReady();
                        }
                    },
                    error: function () {
                        console.debug("error");
                    },
                }
            );

            return this;
        },
        printBill: function (bill) {
            if (bill) {
                var html = this.billPrintTemplate(bill);

                $(html).printArea();
            }

            return this;
        },
        render: function () {
            this.super.render.apply(this);

            var that = this;

            /* First render actions. */
            if (!this.rendered) {
                $.ajax({
                    url: sprintf('%s/%s/%s.print.template.html', App.config.screensFolderUrl, this.name, this.name),
                    async: false,
                    dataType: 'html',
                    success: function (response) {
                        that.billPrintTemplate = Handlebars.compile(response);
                    },
                });

                this.billingItemsGrid = new Backgrid.Grid({
                    columns: [
                        {
                            name: 'code',
                            editable: false,
                            label: 'Código',
                            cell: 'string-center',
                        },
                        {
                            name: 'name',
                            sortable: false,
                            editable: false,
                            label: 'Producto',
                            cell: 'string-center',
                        },
                        {
                            name: 'count',
                            sortable: false,
                            label: 'Cantidad',
                            cell: 'integer',
                        },
                        {
                            name: 'priceTotal',
                            label: 'Precio',
                            sortable: false,
                            editable: false,
                            cell: Backgrid.NumberCell.extend({
                                className: 'number-cell currency-text cell-sm',
                            }),
                            //cell: Backgrid.Extension.CurrencyCell.extend({
                            //    className: 'number-cell currency-cell cell-sm',
                            //}),
                        },
                        {
                            name: 'delete',
                            sortable: false,
                            label: '',
                            cell: Backgrid.Extension.DeleteRowCell.extend({
                                //mustDelete: function () {
                                //    return ($.trim(this.model.get('name')).length != 0);
                                //},
                            }),
                        },
                    ],
                    collection: this.billingItemColl,
                });
                this.billingItemsGrid.render();
                // Render the grid and attach the Grid's root to your HTML document
                this.$el.find('#billingItems').append(this.billingItemsGrid.el);


                var billingHistoryGrid = new Backgrid.Grid({
                    columns: [
                        {
                            name: 'datetime',
                            editable: false,
                            label: 'Fecha Factura',
                            cell: Backgrid.Extension.MomentCenterCell.extend({
                                modelFormat: "YYYY-MM-DD HH:mm:ss.fff",
                                //displayLang: "zh-tw",
                                displayFormat: "dddd DD HH:mm"
                            }),
                        },
                        //{
                        //    name: 'timestamp',
                        //    editable: false,
                        //    label: 'Fecha Creación',
                        //    cell: Backgrid.Extension.MomentCenterCell.extend({
                        //        modelFormat: "YYYY-MM-DD HH:mm:ss.fff",
                        //        //displayLang: "zh-tw",
                        //        displayFormat: "dddd DD HH:mm"
                        //    }),
                        //},
                        {
                            name: 'customer',
                            editable: false,
                            label: 'Cliente',
                            cell: 'string-center',
                        },
                        {
                            name: 'price',
                            editable: false,
                            label: 'Precio',
                            cell: Backgrid.NumberCell.extend({
                                className: 'number-cell currency-text',
                            }),
                        },
                        {
                            name: 'pay',
                            editable: false,
                            label: 'Pago',
                            cell: Backgrid.NumberCell.extend({
                                className: 'number-cell currency-text',
                            }),
                        },
                        {
                            name: 'actions',
                            editable: false,
                            label: '',
                            cell: Backgrid.Extension.ButtonCell.extend({
                                className: 'button-cell action-cell',
                                template: //'<button id="printBtn" class="btn btn-info" title="Imprimir"><i class="fa fa-print"></i></button>'
                                            //+ '<button id="detailsBtn" class="btn btn-warning" title="Detalle"><i class="fa fa-list" ></i></button>'
                                            '<button id="editBtn" class="btn btn-success" title="Editar"><i class="fa fa-pencil-square-o" ></i></button>',
                                events: function () {
                                    return {
                                        'click #editBtn': function (e) { that._billingHistory_editBtn_click(e, this); },
                                        //'click #printBtn': function (e) { that._billingHistory_printBtn_click(e, this); },
                                    };
                                },
                            }),
                        },
                    ],
                    collection: this.billingHistoryColl,
                });
                billingHistoryGrid.render();
                // Render the grid and attach the Grid's root to your HTML document
                this.$el.find('#billingHistory').append(billingHistoryGrid.el);


                this.productTbx = this.$el.find('#productTbx');
                this.customerTbx = this.$el.find('#customerTbx');


                this.modelBinder.bind(
                    this.model,
                    this.el,
                    _.extend(
                        utils.misc.getModelBindingsFromDOM(this.el),
                        {
                            billId: [
                                {
                                    selector: '#cleanBtn',
                                    elAttribute: 'disabled',
                                    converter: function (direction, value) { return !value; },
                                },
                            ],
                            productsAdded: [
                                {
                                    selector: '#billBtn',
                                    elAttribute: 'disabled',
                                    converter: function (direction, value) { return value.length == 0; },
                                },
                                {
                                    selector: '#printBtn',
                                    elAttribute: 'disabled',
                                    converter: function (direction, value) { return value.length == 0; },
                                },
                            ],
                            sealed: [
                                {
                                    selector: $('#billBtn').parent(),
                                    elAttribute: 'class',
                                    converter: function (direction, value, propName, model, elements) {
                                        if (!value)
                                            return $(elements[0]).attr('class').replace('hidden', '') + ' show';
                                        else
                                            return $(elements[0]).attr('class').replace('show', '') + ' hidden';
                                    },
                                },
                                {
                                    selector: $('#newBtn').parent(),
                                    elAttribute: 'class',
                                    converter: function (direction, value, propName, model, elements) {
                                        if (value)
                                            return $(elements[0]).attr('class').replace('hidden', '') + ' show';
                                        else
                                            return $(elements[0]).attr('class').replace('show', '') + ' hidden';
                                    },
                                },
                            ],
                        }
                    )
                );


                /* Indicates that the view was rendered at least one time. */
                this.rendered = true;
            }
            /* Not first render actions. */
            else {
                
            }


            return this;
        },
        resetControls: function () {
            this.billingItemColl.reset();
            this.billModel.reset();

            this.resetProductForm();

            this.syncModels();
        },
        resetProductForm: function () {
            this.model.set({
                product: '',
                productCount: 1,
            });

            this.productTbx.focus();
        },
        save_addBillItem: function (model) {
            App.mainService.runProcedure(
                {
                    Procedure: this.procedures.billItem.insert,
                    Parameters: [
                        { Name: 'billId', Value: this.billModel.get('id'), },
                        { Name: 'productId', Value: model.get('productId'), },
                        { Name: 'count', Value: model.get('count'), },
                    ],
                },
                {
                    success: function (resp) {
                        if (resp.Success == true) {
                            //Set model id.
                            model.set({ id: resp.Data[0][0].Id, });
                        }
                    },
                    error: function () {
                        console.debug("error");
                    },
                }
            );
        },
        save_createBill: function (data, opt) {
            var that = this;

            if (!opt) opt = {};

            App.mainService.runProcedure(
                {
                    Procedure: this.procedures.bill.insert,
                    Parameters: utils.backend.objToQueryParams(data),
                },
                {
                    success: function (resp) {
                        if (resp.Success == true) {
                            //Set model id.
                            that.billModel.set({ id: resp.Data[0][0].Id, });

                            if (opt.success)
                                opt.success(resp);
                        }
                    },
                    error: function () {
                        console.debug("error");
                    },
                }
            );
        },
        sealBill: function () {
            var that = this;

            App.mainService.runProcedure(
                {
                    Procedure: this.procedures.bill.update,
                    Parameters: [
                        { Name: 'id', Value: this.billModel.get('id'), },
                        { Name: 'sealed', Value: true, },
                    ],
                },
                {
                    success: function (resp) {
                        if (resp.Success == true) {
                            var doPrint = confirm("Factura procesada correctamente. ¿Desea imprimirla?");

                            if (doPrint == true)
                                that.printBill(that.getBillForPrint(that.billModel, that.billingItemColl));

                            App.router.navigate('facturacion', { trigger: true, });
                        }
                    },
                    error: function () {
                        console.debug("error");
                    },
                }
            );
        },
        show: function (data) {
            this.billingHistoryColl.fetch();

            if ((!data) || (!data.id))
                this.resetControls();
            else
                this.fetchBill(data.id);

            return this.super.show.apply(this, arguments);
        },
        syncModels: function () {
            var customerText,
                customerModel = this.customersColl.findWhere({ id: this.billModel.get('customerId'), });

            if (customerModel)
                customerText = customerModel.get('code') + ' ' + customerModel.get('name');

            this.model.set({
                billId: this.billModel.get('id'),
                customer: customerText,
                pay: this.billModel.get('pay'),
                productsAdded: this.billingItemColl.toJSON(),
                sealed: this.billModel.get('sealed'),
            });

            this.updateTotalPrice();
        },
        triggerReady: function () {
            if (this.currentBillLoaded && this.customersSync && this.productsSync)
                this.trigger('ready');
        },
        updateTotalPrice: function () {
            //Update total price.
            var totalPrice = 0;

            this.billingItemColl.each(function (model) { totalPrice += model.get('priceTotal'); });

            this.model.set('totalPrice', totalPrice.toFixed(2));
        },

        _addProductBtn_click: function (e) {
            try {
                var prodNumbName = $.trim(this.model.get('product')),
                    prodCount = this.model.get('productCount'),
                    prodCode;

                if (prodNumbName) {
                    prodCode = prodNumbName.split(' ')[0];

                    var result = this.addProduct(prodCode, prodCount);

                    if (result.success == true) {
                        this.resetProductForm();
                    }
                    else {
                        alert(result.message);
                    }
                }
                else {
                    alert('Ingrese un producto.');
                }
            }
            catch (Error) { console.error(Error); }
        },
        _billBtn_click: function (e) {
            try {
                this.sealBill();
            }
            catch (Error) { console.error(Error); }
        },
        _billingHistory_editBtn_click: function (e, cell) {
            try {
                App.router.navigate(sprintf('facturacion/%d', cell.model.get('id')), { trigger: true, });
            }
            catch (Error) { console.error(Error); }
        },
        //_billingHistory_printBtn_click: function (e) {
        //    try {
        //        var that = this;

        //        alert('print');
        //        //this.billModel.fetch(
        //        //    [{ Name: 'id', Value: 12312 }],
        //        //    {
        //        //        success: function (resp) {
        //        //            try
        //        //            {
        //        //                that.billingItemColl.setRaw(resp.Data[1]);
        //        //            }
        //        //            catch (Error) { console.error(Error); }
        //        //        },
        //        //        error: function () {
        //        //            console.debug("error");
        //        //        },
        //        //    }
        //        //);
        //    }
        //    catch (Error) { console.error(Error); }
        //},
        _billingItemColl_add: function (model, coll, options) {
            try {
                if (!this.fetching) {
                    if (model.get('billId')) {
                        this.save_addBillItem(model);
                    }
                    else {
                        var that = this;

                        this.save_createBill(
                            null,
                            {
                                success: function (resp) {
                                    try {
                                        App.router.navigate(sprintf('facturacion/%d', resp.Data[0][0].Id), { trigger: false, });

                                        that.save_addBillItem(model);
                                    }
                                    catch (Error) { console.error(Error); }
                                },
                            }
                        );
                    }
                }
            }
            catch (Error) { console.error(Error); }
        },
        _billingItemColl_addChangeRemoveReset: function (model, coll, options) {
            try {
                this.model.set('productsAdded', this.billingItemColl.toJSON());

                this.updateTotalPrice();
            }
            catch (Error) { console.error(Error); }
        },
        _billingItemColl_change: function (model, coll, options) {
            try {
                if (!this.fetching) {
                    //Do nothing if the changed attr was id.
                    if (model.changed.id == undefined) {
                        App.mainService.runProcedure(
                            {
                                Procedure: this.procedures.billItem.update,
                                Parameters: [
                                    { Name: 'id', Value: model.get('id'), },
                                    { Name: 'count', Value: model.get('count'), },
                                ],
                            },
                            {
                                success: function (resp) {
                                    if (resp.Success == true) {
                                        console.debug(resp);
                                    }
                                },
                                error: function () {
                                    console.debug("error");
                                },
                            }
                        );
                    }
                }
            }
            catch (Error) { console.error(Error); }
        },
        _billingItemColl_remove: function (model, coll, options) {
            try {
                if (!this.fetching) {
                    App.mainService.runProcedure(
                        {
                            Procedure: this.procedures.billItem.delete,
                            Parameters: [
                                { Name: 'id', Value: model.get('id'), },
                            ],
                        },
                        {
                            success: function (resp) {
                                if (resp.Success == true) {
                                    console.debug(resp);
                                }
                            },
                            error: function () {
                                console.debug("error");
                            },
                        }
                    );
                }
            }
            catch (Error) { console.error(Error); }
        },
        _billModel_change: function (model, options) {
            try {
                if (!this.fetching) {
                    //Do nothing if the changed attr was id.
                    if (model.changed.id == undefined) {
                        if (model.get('id')) {
                            App.mainService.runProcedure(
                                {
                                    Procedure: this.procedures.bill.update,
                                    Parameters: utils.backend.objToQueryParams(
                                        model.changed,
                                        [
                                            { Name: 'id', Value: model.get('id'), },
                                        ]
                                    ),
                                },
                                {
                                    success: function (resp) {
                                        if (resp.Success == true) {
                                            console.debug(resp);
                                        }
                                    },
                                    error: function () {
                                        console.debug("error");
                                    },
                                }
                            );
                        }
                        else {
                            this.save_createBill(
                                model.changed,
                                {
                                    success: function (resp) {
                                        try {
                                            App.router.navigate(sprintf('facturacion/%d', resp.Data[0][0].Id), { trigger: false, });
                                        }
                                        catch (Error) { console.error(Error); }
                                    },
                                }
                            );
                        }
                    }
                }
            }
            catch (Error) { console.error(Error); }
        },
        _billModel_changeReset: function (model, options) {
            try {
                this.syncModels();
            }
            catch (Error) { console.error(Error); }
        },
        _cleanBtn_click: function (e) {
            try {
                if (confirm('¿Está seguro de querer borrar la factura?') == true)
                {
                    var that = this;

                    this.cleanBilling({
                        success: function (resp) {
                            App.router.navigate('facturacion', { trigger: true, });
                        },
                    });
                }
            }
            catch (Error) { console.error(Error); }
        },
        _customersCat_fetch_success: function (coll) {
            try {
                this.customersColl = coll;

                var items = [];

                coll.each(function (model) { items.push(model.get('code') + " " + model.get('name')); });

                this.customerTbx = this.$el.find('#customerTbx').typeahead({
                    source: items,
                });


                this.customersSync = true;

                this.triggerReady();
            }
            catch (Error) { console.error(Error); }
        },
        _model_change_customer: function (model, options) {
            try {
                var codeName = $.trim(this.model.get('customer'));

                if (codeName) {
                    var code = codeName.split(' ')[0],
                        model;

                    model = this.customersColl.findWhere({ code: code, });

                    if (model)
                        this.billModel.set({ customerId: model.get('id'), });
                }
                else {
                    this.billModel.set({ customerId: null, });
                }
            }
            catch (Error) { console.error(Error); }
        },
        _model_change_pay: function (model, options) {
            try {
                this.billModel.set({ pay: model.get('pay'), });
            }
            catch (Error) { console.error(Error); }
        },
        _newBtn_click: function (e) {
            try {
                App.router.navigate('facturacion', { trigger: true, });
            }
            catch (Error) { console.error(Error); }
        },
        _printBtn_click: function (e) {
            try {
                this.printBill(this.getBillForPrint(this.billModel, this.billingItemColl));
            }
            catch (Error) { console.error(Error); }
        },
        _productsCat_fetch_success: function (coll) {
            try {
                this.productsColl = coll;

                //var items = [];

                //coll.each(function (model) { items.push(model.get('code') + " " + model.get('name')); });

                this.productTbx = this.$el.find('#productTbx').typeahead({
                    displayText: function (obj) { return obj.code + ' ' + obj.name; },
                    source: coll.toJSON(),
                });


                this.productsSync = true;

                this.triggerReady();
            }
            catch (Error) { console.error(Error); }
        },
    });

    return View;
});